Por lo general, cuando se trabaja con un archivo se hacen tres operaciones seguidas:
Y hay que tener cuidado, porque si ocurre algún error con el archivo en algún punto de su procesamiento es necesario encargarse de cerrarlo, antes de que la excepción siga subiendo niveles.
Para trabajar con los archivos de una forma más simple es que se agregó la sentencia with que define un contexto dentro del cual nos asegura que, ocurra una excepción o no, el archivo se cerrará al momento de salir de ese contexto:
In [1]:
try:
with open('ejemplo.txt') as fd:
print '¿El archivo se encuentra cerrado?', fd.closed
a += 2 # Como la variable a no existe, va a tirar
# una excepción del tipo NameError
print 'Estas líneas nunca se van a mostrar porque'
print 'antes va a ocurrir un error'
except NameError:
print 'Ocurrio un error'
print '¿El archivo se encuentra cerrado?', fd.closed
In [2]:
with open('ejemplo.txt', 'r') as archivo:
print '¿El archivo se encuentra cerrado?: {}'.format(archivo.closed)
print
for linea in archivo:
longitud = len(linea[:-1])
print '{:2}: {}'.format(longitud, linea[:-1])
print
print '¿El archivo se encuentra cerrado?: {}'.format(archivo.closed)
Si bien no cerramos explícitamente el archivo usando la función close, al salir del bloque de código que encierra el with el archivo se encontrará cerrado.
Los pickles son una forma de guardar estructuras de datos complejas y recuperarlas fácilmente, sin necesidad de convertirlas a texto y luego parsearlas:
Se puede usar los pickles como se hacía con los viejos archivos de Pascal, donde se guardaba un registro detrás del otro; pero con la diferencia de que en este caso no es necesario que todos los registros sean del mismo tipo:
In [3]:
import pickle # Importo la biblioteca necesaria
# Creo la variable archivo
with open('ejemplo.pkl', 'wb') as archivo:
pkl = pickle.Pickler(archivo) # Creo mi punto de acceso a los datos a partir del archivo
lista1 = [1, 2, 3]
lista2 = [4, 5]
diccionario = {'campo1': 1, 'campo2': 'dos'}
pkl.dump(lista1) # Guardo la lista1 de [1, 2, 3]
pkl.dump(None) # Guardo el valor None
pkl.dump(lista2)
pkl.dump('Hola mundo')
pkl.dump('')
pkl.dump(diccionario)
pkl.dump(1)
Para leer de un archivo pickle no puedo usar el método readline que usa la estructura for, por lo que no me queda otra que siempre intentar leer hasta que lance una excepción del tipo EOFError:
In [4]:
import pickle
with open('ejemplo.pkl', 'rb') as archivo:
print pickle.load(archivo) # lista1
print pickle.load(archivo) # None
print pickle.load(archivo) # lista2
print pickle.load(archivo) # Hola mundo
print pickle.load(archivo) # ''
print pickle.load(archivo) # diccionario
print pickle.load(archivo) # 1
print pickle.load(archivo) # Fin de archivo
In [7]:
with open('ejemplo.pkl', 'rb') as archivo:
seguir_leyendo = True
while seguir_leyendo:
try:
dato = pickle.load(archivo) # Leo del archivo un elemento
print dato
except EOFError:
seguir_leyendo = False
Así como en el ejemplo anterior guardamos de a un elemento por vez, también podríamos guardar una lista completa que tenga todos los elementos en memoria. De ésta forma, los archivos podrían usarse para cargar los datos al comenzar el programa y guardarlos todos juntos antes de terminar.
Suponiendo que estoy desarrollando un juego en que no van a haber muchos jugadores compitiendo entre si, podría tener una lista con los puntajes y hacer:
In [5]:
lista = [ # Creo la lista que quiero guardar
{'usuario': 'csanchez', 'puntaje': 5},
{'usuario': 'pperez', 'puntaje': 3},
{'usuario': 'jromero', 'puntaje': 1},
]
# Guardo la lista en el archiv
with open('ejemplo_2.pkl', 'wb') as archivo:
pkl = pickle.Pickler(archivo)
pkl.dump(lista)
Y si ahora quiero sumarle 3 puntos a un usuario en particular tendría que:
In [6]:
def imprimir_puntajes(lista_puntajes):
for puntaje in lista_puntajes:
print ' ', puntaje
# Leo del archivo
with open('ejemplo_2.pkl', 'rb') as archivo:
lista_puntajes = pickle.load(archivo)
# Actualizo el puntaje
print 'La lista antes de hacer el cambio es:'
imprimir_puntajes(lista_puntajes)
pos = 0
lista_puntajes[pos]['puntaje'] += 3
print 'La lista una vez hecho el cambio es:'
imprimir_puntajes(lista_puntajes)
# Guardo la lista en el archiv
with open('ejemplo_2.pkl', 'wb') as archivo:
pkl = pickle.Pickler(archivo)
pkl.dump(lista_puntajes)
Si bien es muy práctica esta alternativa, tiene el gran inconveniente de no hacer un uso eficiente de la memoria.
Si el archivo contiene millones de usuarios, los estaríamos levantando todos a memoria, con el gran costo que tiene eso (no sólo en espacio, sino también en tiempo) con el único objetivo de sumarle 3 puntos a un único usuario. Y una vez que actualizamos el puntaje de ese usuario, tendríamos que volver a guardar todo el archivo en el disco.
Si bien el uso de los pickles puede resultar muy útil, la forma de leer la información guardada en ellos no suele ser muy cómoda. Por lo que podríamos implementar en un archivo utils.py
las siguientes dos funciones para abstraernos un poco de cómo se accede a los datos:
# encoding: utf8
import pickle
def guardar_en_archivo(archivo, contenido):
"""Guarda lo que le pasen como segundo parámetro en el archivo
que recibe como primer parámetro.
El parámetro llamado archivo tiene que estar abieto en modo
binario y para escritura (wb)
"""
pickler = pickle.Pickler(archivo)
pickler.dump(contenido)
def leer_desde_archivo(archivo, valor_por_defecto=None):
"""Lee del archivo archivo un registro y lo retorna junto con una
variable booleana que indica si llegó al fin de archivo o no.
El parámetro llamado archivo tiene que estar abieto en modo
binario y para lectura (rb).
Si se intenta leer más allá del fin de archivo, data valdrá lo que le
hayan pasado en valor_por_defecto (si no le pasan nada será None)
y fin_de_archivo será True. En cualquier otro caso fin_de_archivo
será False.
"""
try:
data = pickle.load(archivo)
fin_de_archivo = False
except EOFError:
data = valor_por_defecto
fin_de_archivo = True
return data, fin_de_archivo
En este caso, se podría considerar que la función leer_desde_archivo
funciona similar a cómo lo hacen los archivos con un registro centinella.
Por lo que podríamos usar:
In [7]:
import utils
curso = [
{'nombre': 'Sanchez, Lucas', 'nota': 8, 'padron': 90431, 'grupo': 1},
{'nombre': 'Alvarez, Javier', 'nota': 2, 'padron': 92953, 'grupo': 1},
{'nombre': 'Perez, Matias', 'nota': 10, 'padron': 92407, 'grupo': 1},
{'nombre': 'Lopez, Pablo', 'nota': 9, 'padron': 96556, 'grupo': 2},
{'nombre': 'Gonzalez, Marcelo', 'nota': 7, 'padron': 92143, 'grupo': 2},
{'nombre': 'Rodriguez, Pablo', 'nota': 9, 'padron': 92431, 'grupo': 2},
{'nombre': 'Gomez, Matias', 'nota': 4, 'padron': 98306, 'grupo': 3},
{'nombre': 'Diaz, Juan', 'nota': 8, 'padron': 97972, 'grupo': 3},
{'nombre': 'Garcia, Matias', 'nota': 2, 'padron': 93108, 'grupo': 4},
{'nombre': 'Rodriguez, Agustin', 'nota': 5, 'padron': 96739, 'grupo': 5},
]
print 'Creo el archivo vacío usando el modo "wb"'
print 'Si tenía algo, ya lo borre...'
MAX = {'padron': 999999999999}
with open('curso.pkl', 'wb') as archivo:
for alumno in curso:
print 'Guardando el alumno {} en el archivo'.format(alumno)
utils.guardar_en_archivo(archivo, alumno)
print
print 'Abro el archivo en modo lectura...'
with open('curso.pkl', 'rb') as archivo:
alumno, fin_de_archivo = utils.leer_desde_archivo(archivo)
while not fin_de_archivo:
print 'Leyendo el alumno {} en el archivo'.format(alumno)
alumno, fin_de_archivo = utils.leer_desde_archivo(archivo)
Cuando estamos hablando de archivos y nos referimos a corte de control estamos haciendo referencia al algoritmo que toma un archivo ordenado, por una o más claves, y como resultado del mismo nos devuelve un "resumen" del mismo.
Por ejemplo, si tenemos el siguiente archivo ordenado por código de cliente:
Código de cliente | Número de factura | Monto de la factura |
---|---|---|
001 | 2020452 | 916 |
002 | 12069115 | 772 |
002 | 14534467 | 264 |
002 | 1424980 | 752 |
002 | 16214863 | 424 |
003 | 6882583 | 590 |
003 | 18817277 | 654 |
003 | 1944327 | 211 |
003 | 16837776 | 595 |
003 | 10145610 | 444 |
004 | 4671025 | 393 |
004 | 13453769 | 556 |
005 | 7126081 | 35 |
005 | 16497082 | 367 |
Y queremos calcular cuánta plata gastó cada cliente en nuestro negocio:
El cliente 001 gastó 916
El cliente 002 gastó 2212
El cliente 003 gastó 2494
El cliente 004 gastó 949
El cliente 005 gastó 402
Podríamos usar el siguiente algoritmo para generar el reporte:
In [8]:
import utils
def crear_archivo_de_ventas():
ventas = [
{'cliente': '001', 'nro_factura': 2020452, 'monto': 916},
{'cliente': '002', 'nro_factura': 12069115, 'monto': 772},
{'cliente': '002', 'nro_factura': 14534467, 'monto': 264},
{'cliente': '002', 'nro_factura': 1424980, 'monto': 752},
{'cliente': '002', 'nro_factura': 16214863, 'monto': 424},
{'cliente': '003', 'nro_factura': 6882583, 'monto': 590},
{'cliente': '003', 'nro_factura': 18817277, 'monto': 654},
{'cliente': '003', 'nro_factura': 1944327, 'monto': 211},
{'cliente': '003', 'nro_factura': 16837776, 'monto': 595},
{'cliente': '003', 'nro_factura': 10145610, 'monto': 444},
{'cliente': '004', 'nro_factura': 4671025, 'monto': 393},
{'cliente': '004', 'nro_factura': 13453769, 'monto': 556},
{'cliente': '005', 'nro_factura': 7126081, 'monto': 35},
{'cliente': '005', 'nro_factura': 16497082, 'monto': 367}
]
print 'Creo el archivo vacío usando el modo "wb"'
with open('ventas.pkl', 'wb') as archivo:
for venta in ventas:
utils.guardar_en_archivo(archivo, venta)
def mostrar_ventas_por_cliente(archivo):
valor_por_defecto = {'cliente': None, 'monto':0}
total = 0
# Leo el primer registro del archivo
venta, fin_de_archivo = utils.leer_desde_archivo(archivo, valor_por_defecto)
codigo_cliente = venta['cliente']
while not fin_de_archivo:
codigo_cliente = venta['cliente']
subtotal = 0 # Inicializo las ventas de este cliente
# Mientras siga procesando el mismo cliente...
while venta['cliente'] == codigo_cliente:
total += venta['monto'] # Acumulo las ventas totales
subtotal += venta['monto'] # Acumulo las ventas de este cliente
venta, fin_de_archivo = utils.leer_desde_archivo(archivo, valor_por_defecto)
print ' El cliente {cliente} gastó {monto:4}'.format(cliente=codigo_cliente, monto=subtotal)
print 'El total es de ${}'.format(total)
crear_archivo_de_ventas()
print 'Abro el archivo en modo lectura...'
# Abro el archivo usando el with para asegurarme
# que, pase lo que pase, el archivo quede cerrado
with open('ventas.pkl', 'rb') as archivo:
mostrar_ventas_por_cliente(archivo)
¿Y si el archivo fuera de texto?
Es simple, tratamos de llevar el problema a la solución que conocemos. Para eso podríamos crearnos una función que se comporte de una forma similar a la que se encuentra en utils:
def leer_desde_archivo(archivo, valor_por_defecto):
try:
linea = archivo.readline()
codigo_cliente, factura, monto = linea.strip().split(',')
data = {
'cliente': codigo_cliente,
'factura': int(factura),
'monto': int(monto)
}
fin_de_archivo = False
except StopIteration:
data = valor_por_defecto
fin_de_archivo = True
return data, fin_de_archivo
Esta función, no sólo lee cada línea, sino que una vez leída:
strip
para quitar el \n
que tiene al final de la líneasplit
para separar el string por comasint
Por último, si ya habíamos llegado al final del archivo e intentamos leer de nuevo, el intérprete va a lanzar la excepción StopIteration
que la capturamos con el try-except
y, en ese caso, devolvemos el valor que nos pasaron por parámetro.
Entonces, después el algoritmo nos queda igual, a excepción de que ahora no importamos a la utils y la forma de crear y abrir el archivo va a ser distinta:
In [9]:
def leer_desde_archivo(archivo, valor_por_defecto):
try:
linea = archivo.readline()
codigo_cliente, factura, monto = linea.strip().split(',')
data = {
'cliente': codigo_cliente,
'factura': int(factura),
'monto': int(monto)
}
fin_de_archivo = False
except Exception:
data = valor_por_defecto
fin_de_archivo = True
return data, fin_de_archivo
def crear_archivo_de_ventas():
ventas = """001,2020452,916
002,12069115,772
002,14534467,264
002,1424980,752
002,16214863,424
003,6882583,590
003,18817277,654
003,1944327,211
003,16837776,595
003,10145610,444
004,4671025,393
004,13453769,556
005,7126081,35
005,16497082,367
"""
print 'Creo el archivo vacío usando el modo "wt"'
with open('ventas.csv', 'wt') as archivo:
archivo.write(ventas)
def mostrar_ventas_por_cliente(archivo):
valor_por_defecto = {'cliente': None, 'monto':0}
total = 0
# Leo el primer registro del archivo
venta, fin_de_archivo = leer_desde_archivo(archivo, valor_por_defecto)
codigo_cliente = venta['cliente']
while not fin_de_archivo:
codigo_cliente = venta['cliente']
subtotal = 0 # Inicializo las ventas de este cliente
# Mientras siga procesando el mismo cliente...
while venta['cliente'] == codigo_cliente:
total += venta['monto'] # Acumulo las ventas totales
subtotal += venta['monto'] # Acumulo las ventas de este cliente
venta, fin_de_archivo = leer_desde_archivo(archivo, valor_por_defecto)
print ' El cliente {cliente} gastó {monto:4}'.format(cliente=codigo_cliente, monto=subtotal)
print 'El total es de ${}'.format(total)
crear_archivo_de_ventas()
print 'Abro el archivo en modo lectura...'
# Abro el archivo usando el with para asegurarme
# que, pase lo que pase, el archivo quede cerrado
with open('ventas.csv', 'rt') as archivo:
mostrar_ventas_por_cliente(archivo)
El merge, o apareo, de archivos consiste en tener dos o más archivos que se encuentran ordenados por una misma clave y se quieren procesar leyéndolos una única vez y generar un reporte o un nuevo archivo con dicha información consolidada. Supongamos que tenemos el siguiente código para crear unos archivos de prueba:
In [11]:
import utils
oper = [
{'cta': 1, 'imp': 800},
{'cta': 1, 'imp': 250},
{'cta': 2, 'imp': 700},
{'cta': 2, 'imp': 700},
{'cta': 10, 'imp': 1000},
]
with open('movs1.pkl', 'wb') as archivo:
for movimiento in oper:
print 'Guardando la operacion {} en el archivo movs1.pkl'.format(movimiento)
utils.guardar_en_archivo(archivo, movimiento)
print
operaciones_2 = [
{'cta': 1, 'imp': 800},
{'cta': 2, 'imp': 700},
{'cta': 3, 'imp': 700},
{'cta': 10, 'imp': 100},
{'cta': 15, 'imp': 3},
]
with open('movs2.pkl', 'wb') as archivo:
for movimiento in operaciones_2:
print 'Guardando la operacion {} en el archivo movs2.pkl'.format(movimiento)
utils.guardar_en_archivo(archivo, movimiento)
Entonces si lo que quiero es mostrar el estado de cada una de estas cuentas podría hacer:
In [12]:
import utils
with open('movs1.pkl', 'rb')as movs1, open('movs2.pkl', 'rb') as movs2:
MAX = {'cta': 99999999, 'imp':0}
oper1, eof1 = utils.leer_desde_archivo(movs1, MAX)
oper2, eof2 = utils.leer_desde_archivo(movs2, MAX)
total = 0
while not eof1 or not eof2:
totcta = 0
men = min(oper1['cta'], oper2['cta'])
print 'La menor de las cuentas entre {} y {} es {}'.format(
oper1['cta'],
oper2['cta'],
men
)
while oper1['cta'] == men:
print 'Procesando la cuenta {} de movs1'.format(oper1['cta'])
total += oper1['imp']
totcta += oper1['imp']
oper1, eof1 = utils.leer_desde_archivo(movs1, MAX)
while oper2['cta'] == men:
print 'Procesando la cuenta {} de movs2'.format(oper2['cta'])
total += oper2['imp']
totcta += oper2['imp']
oper2, eof2 = utils.leer_desde_archivo(movs2, MAX)
print 'Total por cta:', men , totcta
print 'Total Gral:', total
Cuando tiene toda la información en un único archivo (comúnmente llamado archivo maestro) y en cierto momento se la quiere actualizar a partir de un segundo archivo llamado novedades se genera un tercer archivo con toda la información consolidada.
Los archivos maestro y novedades deberán estar ordenados por la misma clave, por lo que el nuevo archivo maestro también debe quedar ordenado.
Por ejemplo, si contamos con un archivo llamado cuentas.pkl que en casa posición tiene la información correspondiente a una cuenta bancaria:
Y uno que tenga las novedades diarias llamado movimientos.pkl con la siguiente información:
In [13]:
import utils
def crear_archivo_maestro():
cuentas = [
{'nro_cuenta': 1, 'saldo': 7094, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_1'},
{'nro_cuenta': 2, 'saldo': 2896, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_2'},
{'nro_cuenta': 3, 'saldo': 14424, 'moneda': '$',
'tipo_cuenta': 'corriente', 'titular': 'cliente_3'},
{'nro_cuenta': 5, 'saldo': 7156, 'moneda': '$',
'tipo_cuenta': 'corriente', 'titular': 'cliente_5'},
{'nro_cuenta': 8, 'saldo': 7500, 'moneda': '$',
'tipo_cuenta': 'corriente', 'titular': 'cliente_8'},
{'nro_cuenta': 9, 'saldo': 2128, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_9'},
{'nro_cuenta': 13, 'saldo': 13524, 'moneda': '$',
'tipo_cuenta': 'corriente', 'titular': 'cliente_13'},
{'nro_cuenta': 15, 'saldo': 9479, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_15'},
{'nro_cuenta': 21, 'saldo': 8462, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_21'},
{'nro_cuenta': 25, 'saldo': 6258, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_25'},
{'nro_cuenta': 32, 'saldo': 14082, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_32'}
]
with open('cuentas.pkl', 'wb') as archivo:
for cuenta in cuentas:
utils.guardar_en_archivo(archivo, cuenta)
def crear_archivo_novedades():
novedades = [
{'nro_cuenta': 1, 'tipo': 'B'},
{'nro_cuenta': 2, 'monto': 731,
'tipo_movimiento': 'debito', 'tipo': 'M'},
{'nro_cuenta': 3, 'monto': 791,
'tipo_movimiento': 'debito', 'tipo': 'M'},
{'nro_cuenta': 4, 'moneda': '$',
'tipo_cuenta': 'corriente',
'titular': 'cliente_4', 'tipo': 'A'},
{'nro_cuenta': 8, 'monto': 750,
'tipo_movimiento': 'debito', 'tipo': 'M'},
{'nro_cuenta': 11, 'moneda': '$',
'tipo_cuenta': 'corriente', 'titular': 'cliente_11',
'tipo': 'A'},
{'nro_cuenta': 13, 'monto': 481,
'tipo_movimiento': 'debito', 'tipo': 'M'},
{'nro_cuenta': 15, 'tipo': 'B'},
{'nro_cuenta': 16, 'moneda': '$',
'tipo_cuenta': 'debito', 'titular': 'cliente_16',
'tipo': 'A'},
{'nro_cuenta': 19, 'moneda': '$',
'tipo_cuenta': 'corriente', 'titular': 'cliente_19',
'tipo': 'A'},
{'nro_cuenta': 21, 'monto': 653,
'tipo_movimiento': 'debito', 'tipo': 'M'},
{'nro_cuenta': 25, 'tipo': 'B'},
{'nro_cuenta': 32, 'tipo': 'B'},
]
with open('movimientos.pkl', 'wb') as archivo:
for nov in novedades:
utils.guardar_en_archivo(archivo, nov)
################### Apareo ###################
def dar_de_alta(archivo, novedad):
del novedad['tipo'] # Le borro el campo tipo que no
# existe en el archivo maestro
novedad['saldo'] = 0 # Inicializo el saldo en 0
utils.guardar_en_archivo(archivo, novedad)
def modificar_cuenta(archivo, cuenta, novedad):
if novedad['tipo_movimiento'] == 'credito':
monto = novedad['monto']
else:
monto = -1 * novedad['monto']
cuenta['saldo'] += monto
utils.guardar_en_archivo(archivo, cuenta)
def apareo(maestro, novedades, nuevo):
cuenta, eof_ctas = utils.leer_desde_archivo(maestro)
nov, eof_novs = utils.leer_desde_archivo(novedades)
while not eof_ctas and not eof_novs:
print 'Procesando cuenta nro {} y novedad {} del tipo {}'.format(
cuenta['nro_cuenta'], nov['nro_cuenta'], nov['tipo']
)
if nov['nro_cuenta'] < cuenta['nro_cuenta'] and nov['tipo'] == 'A':
# Si es un alta, acomodo el registro y lo guardo
dar_de_alta(nuevo, nov)
nov, eof_novs = utils.leer_desde_archivo(novedades)
# No puede ser una B o M porque habría un error
elif nov['nro_cuenta'] == cuenta['nro_cuenta']:
if nov['tipo'] == 'M':
# Si es una modificación, actualizo la cuenta,
# guardo y leo de los dos archivos
modificar_cuenta(nuevo, cuenta, nov)
cuenta, eof_ctas = utils.leer_desde_archivo(maestro)
nov, eof_novs = utils.leer_desde_archivo(novedades)
# Si fuera una B, tendría que ignorarlos y leer de
# los archivos igual.
# No puede ser una A porque habría un error
elif nov['nro_cuenta'] > cuenta['nro_cuenta']:
# Si la novedad tiene un número de cuenta mayor,
# significa que para esa cuenta no hubo novedades
# por lo que la guardo tal cual esta sin modificar
# y leo la siguiente
utils.guardar_en_archivo(nuevo, cuenta)
cuenta, eof_ctas = utils.leer_desde_archivo(maestro)
# Como salí del while, termine con al menos uno de los
# dos archivos, por lo que ahora puedeo leer lo que
# quedaba y guardarlo casi tal cual vienen
while not eof_ctas:
print 'Procesando cuenta nro {}'.format(cuenta['nro_cuenta'])
utils.guardar_en_archivo(nuevo, cuenta)
cuenta, eof_ctas = utils.leer_desde_archivo(maestro)
while not eof_novs:
print 'Procesando la novedad {} del tipo {}'.format(
nov['nro_cuenta'], nov['tipo']
)
del nov['tipo']
nov['saldo'] = 0
utils.guardar_en_archivo(nuevo, nov)
nov, eof_novs = utils.leer_desde_archivo(novedades)
def mostrar_archivo_nuevo():
print 'El archivo nuevo tiene los registros:'
with open('nuevo.pkl', 'rb') as nuevo:
cuenta, eof_ctas = utils.leer_desde_archivo(nuevo)
while not eof_ctas:
print cuenta
cuenta, eof_ctas = utils.leer_desde_archivo(nuevo)
crear_archivo_maestro()
crear_archivo_novedades()
with open('cuentas.pkl', 'rb') as maestro, \
open('movimientos.pkl', 'rb') as novedades, \
open('nuevo.pkl', 'wb') as nuevo:
apareo(maestro, novedades, nuevo)
mostrar_archivo_nuevo()
def guardar_en_archivo(archivo, contenido):
"""Guarda lo que le pasen como segundo parámetro en el archivo
que recibe como primer parámetro.
El parámetro llamado archivo tiene que estar abieto en modo
binario y para escritura (wb)
"""
...
def leer_desde_archivo(archivo, valor_por_defecto=None):
"""Lee del archivo archivo un registro y lo retorna junto con una
variable booleana que indica si llegó al fin de archivo o no.
El parámetro llamado archivo tiene que estar abieto en modo
binario y para lectura (rb).
Si se intenta leer más allá del fin de archivo, data valdrá lo que le
hayan pasado en valor_por_defecto (si no le pasan nada será None)
y fin_de_archivo será True. En cualquier otro caso fin_de_archivo
será False.
"""
...
return data, fin_de_archivo
Leer dos archivos (61_matematica.dat y 75_computacion.dat) que tendrán registros con los campos:
* padron
* nombre
* apellido
* nota
* codigo_departamento
* codigo_materia
y armar uno nuevo donde sólo figuren las notas de los alumnos aprobados ordenados por padrón.
Ambos archivos están ordenados por padrón y se deben leer una única vez. Como los archivos pueden ser muy grandes, no se pueden guardar en memoria.
Una vez procesados los dos archivos se tienen que informar, para cada materia, cuántos alumnos aprobaron y cuántos desaprobaron.